package com.atguigu.spzx.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import jakarta.annotation.Resource;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.Mono;

/**
 * ClassName: AuthGlobalFilter
 * Package: com.atguigu.spzx.gateway.filter
 * Description:
 *
 * @Author 刘强
 * @Create 2024/7/16 15:56
 * @Version 1.0
 */
@Component
public class AuthGlobalFilter implements GlobalFilter {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 统一认证
     * @param exchange the current server exchange
     * @param chain provides a way to delegate to the next filter
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 1. 判断用户访问的接口是否需要认证
        String path = request.getURI().getPath();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        if(!antPathMatcher.match("/**/auth/**",path)){
            // 不需要认证，则直接放行
            return chain.filter(exchange);
        }
        // 2. 获取token，然后从redis中获取用户信息，如果未空则未登录，响应错误结果，否则放行
        String token = request.getHeaders().getFirst("token");
        String userInfoJson = stringRedisTemplate.opsForValue().get("user:login:" + token);
        if(StringUtils.isEmpty(userInfoJson)){
            // 用户未登录，设置错误响应
            DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONBytes(Result.build(null,ResultCodeEnum.LOGIN_AUTH)));
            // 设置响应体类型
            response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }
}
